<template>
  <div class="container">
    <!-- 左侧查询栏 -->
    <div class="left">
      <div class="title">
        <div class="check_label">
          <el-checkbox
            style="height: 14px; padding-right: 8px"
            v-model="leftCheckAll"
            :indeterminate="leftIsIndeterminate"
            @change="leftHandleCheckAllChange"
          >
          </el-checkbox>
          <span>用户列表</span>
        </div>

        <div>{{ userSelectComputed }}</div>
      </div>

      <div class="searchIput">
        <el-input v-model="leftInput" placeholder="输入账号或者昵称" clearable>
          <template #prefix>
            <el-icon class="el-input__icon"><Search /></el-icon>
          </template>

          <template #append>
            <el-button
              type="primary"
              :icon="Search"
              circle
              color="#626aef"
              @click="queryPageUserList"
            />
          </template>
        </el-input>
      </div>

      <div class="optionBox">
        <div class="optionList">
          <el-checkbox-group
            v-model="leftCheckOptionValue"
            @change="leftHandleCheckedChange"
          >
            <el-checkbox
              border
              :label="item.label"
              :value="item.value"
              :disabled="judgeDisabled(item.value)"
              v-for="item in leftCheckOption"
              :key="item.value"
              style="margin-bottom: 10px"
            >
              {{ item.label }}
            </el-checkbox>
          </el-checkbox-group>
        </div>

        <div class="paginationBar">
          <el-pagination
            v-model:current-page="pageNum"
            v-model:page-size="pageSize"
            :background="true"
            size="small"
            :total="total"
            :page-sizes="[20, 30, 40, 50, 60]"
            layout="total, prev, pager, next"
            @size-change="handlePageSizeChange"
            @current-change="handlePageNumChange"
          />
        </div>
      </div>

      <!-- 侧边按钮栏 -->
      <div class="btnBox">
        <div>
          <el-button
            color="#626aef"
            :disabled="leftCheckOptionValue.length == 0"
            plain
            @click="toRight(leftCheckOptionValue)"
          >
            右移
          </el-button>
        </div>
        <div>
          <el-button
            color="#529b2e"
            plain
            :disabled="leftCheckOptionValue.length == 0"
            @click="setRoleUsers(UserDataSetTypeEnum.ADD, leftCheckOptionValue)"
          >
            添加
          </el-button>
        </div>
      </div>
    </div>

    <div class="center">
      <div class="text">
        <span class="label">右移</span>
        <span>将左侧选项框中选项添加到右侧选项框中，后台数据不更新</span>
      </div>
      <div class="text">
        <span class="label">添加</span>
        <span>将左侧选项框中选项添加到右侧选项框中，后台数据更新</span>
      </div>

      <br />

      <div class="text">
        <span class="label">移除</span>
        <span>将右侧选项框中选项移除，后台数据不更新</span>
      </div>
      <div class="text">
        <span class="label">删除</span>
        <span>将右侧选项框中选项移除，后台数据更新</span>
      </div>
      <div class="text">
        <span class="label">重置</span>
        <span
          >将右侧后台原有数据全部删除，更新为当前右侧选项框已选择的数据</span
        >
      </div>
    </div>

    <!-- 右侧详情栏 -->
    <div class="right">
      <div class="title">
        <div class="check_label">
          <el-checkbox
            style="height: 14px; padding-right: 8px"
            v-model="rightCheckAll"
            :indeterminate="rightIsIndeterminate"
            @change="rightHandleCheckAllChange"
          >
          </el-checkbox>

          <span>角色用户</span>
        </div>
        <div>{{ roleUserSelectComputed }}</div>
      </div>

      <div class="searchIput">
        <el-input v-model="rightInput" placeholder="输入账号或者昵称" clearable>
          <template #prefix>
            <el-icon class="el-input__icon"><Search /></el-icon>
          </template>
        </el-input>
      </div>

      <div class="optionBox">
        <div class="optionList">
          <el-checkbox-group
            v-model="rightCheckOptionValue"
            @change="rightHandleCheckedChange"
          >
            <el-checkbox
              border
              :label="item.label"
              :value="item.value"
              v-for="item in rightCheckOption"
              :key="item.value"
              style="margin-bottom: 10px"
            >
              {{ item.label }}
            </el-checkbox>
          </el-checkbox-group>
        </div>

        <!-- <div class="paginationBar"></div> -->
      </div>

      <!-- 侧边按钮栏 -->
      <div class="btnBox">
        <div>
          <el-button
            color="#626aef"
            :disabled="rightCheckOptionValue.length == 0"
            @click="rightRemove(rightCheckOptionValue)"
          >
            移除
          </el-button>
        </div>
        <div>
          <el-button
            color="#F56C6C"
            plain
            :disabled="rightCheckOptionValue.length == 0"
            @click="
              setRoleUsers(UserDataSetTypeEnum.REMOVE, rightCheckOptionValue)
            "
          >
            删除
          </el-button>
        </div>
        <div>
          <el-button
            color="#626aef"
            plain
            :disabled="rightCheckOptionValue.length == 0"
            @click="
              setRoleUsers(UserDataSetTypeEnum.REFRESH, rightCheckOptionValue)
            "
          >
            重置
          </el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, computed } from 'vue'
import { Search } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import type { CheckboxValueType } from 'element-plus'
import { setRoleUsersApi, getRoleUsersDetailApi } from '@/request/api/userRoles'
import { queryPageUserByEasyApi } from '@/request/api/user'
import { UserDataSetTypeEnum } from '@/type/enum'
import { useMessageAlertStore } from '@/features/store/componentStore'
import { throttle } from '@/utils/func'

const props = defineProps({
  roleInfo: { type: Object as () => RoleItf, default: {} },
})

const { openAlert } = useMessageAlertStore()

onMounted(() => {
  queryPageUserList()
  getRoleUsersDetail()
})

interface CheckBoxOptionItf {
  label: string
  value: string
}

// 左侧角色用户筛选文本
const leftInput = ref<string>('')
// 左侧角色用户选项勾选值
const leftCheckOptionValue = ref<string[]>([])
// 左侧角色用户选项列表
const leftCheckOption = ref<CheckBoxOptionItf[]>([])
// 左侧角色用户选项 Map
const leftCheckOptionMap = ref<Map<string, string>>(new Map())

// 分页查询相关
const total = ref<number>(0)
const pageNum = ref<number>(1)
const pageSize = ref<number>(20)
const handlePageNumChange = (val: number) => {
  pageNum.value = val
  queryPageUserList()
}
const handlePageSizeChange = (val: number) => {
  pageSize.value = val
  queryPageUserList()
}

// 查询用户的条件
const queryUserCondition = ref<QueryUserConditionItf>({
  account: null,
  nickName: null,
})

// 条件查询用户
const queryPageUserList = async () => {
  queryUserCondition.value.account = leftInput.value
  queryUserCondition.value.nickName = leftInput.value

  const res = await queryPageUserByEasyApi(
    pageNum.value,
    pageSize.value,
    queryUserCondition.value
  )
  if (res.code !== 200) return openAlert.error(res.message)

  total.value = res.data.total
  leftCheckOptionMap.value = new Map()

  leftCheckOption.value = res.data.records.map((item) => {
    const str = item.nickname + ' @' + item.account

    leftCheckOptionMap.value.set(item.id, str)
    return { value: item.id, label: str }
  })
}

// 左侧选项 与 勾选选项 比例
const userSelectComputed = computed(() => {
  // 选项总数
  const ll = leftCheckOption.value.length
  // 勾选数
  const l = leftCheckOptionValue.value.length

  return l + '/' + ll
})

// 判断是否禁用
const judgeDisabled = (id: string) => {
  return rightCheckOptionMap.value.get(id) != null
}

// 左侧全选
const leftCheckAll = ref(false)
// 左侧全选框中间状态
const leftIsIndeterminate = ref(false)

// 左侧全选状态变化
const leftHandleCheckAllChange = (val: CheckboxValueType) => {
  const temp = leftCheckOption.value.filter((item) => {
    return rightCheckOptionMap.value.get(item.value) == null
  })

  const value: string[] = temp.map((item) => item.value)
  leftCheckOptionValue.value = val ? value : []
  leftIsIndeterminate.value = false
}

// 左侧选项框值的变化
const leftHandleCheckedChange = (value: CheckboxValueType[]) => {
  const checkedCount = value.length
  const temp = leftCheckOption.value.filter((item) => {
    return rightCheckOptionMap.value.get(item.value) == null
  })

  leftCheckAll.value = checkedCount === temp.length
  leftIsIndeterminate.value = checkedCount > 0 && checkedCount < temp.length
}

// 右侧角色用户筛选文本
const rightInput = ref<string>('')
// 右侧角色用户选项勾选值
const rightCheckOptionValue = ref<string[]>([])
// 右侧角色用户选项列表
const rightCheckOption = ref<CheckBoxOptionItf[]>([])
// 右侧角色用户选项 Map
const rightCheckOptionMap = ref<Map<string, string>>(new Map())
// 右侧角色用户选项列表
const roleUserList = ref<CheckBoxOptionItf[]>([])

// 获取角色用户列表
const getRoleUsersDetail = async () => {
  const queryCondition = {
    roleId: props.roleInfo.id,
    account: '',
    nickname: '',
  }
  const res = await getRoleUsersDetailApi(queryCondition)
  if (res.code !== 200) return openAlert.error(res.message)

  rightCheckOptionMap.value = new Map()

  roleUserList.value = res.data.map((item) => {
    const str = item.nickname + ' @' + item.account

    rightCheckOptionMap.value.set(item.id, str)
    return { value: item.id, label: str }
  })
  rightCheckOption.value = res.data.map((item) => {
    const str = item.nickname + ' @' + item.account
    return { value: item.id, label: str }
  })
}

// 右侧选项 与 勾选选项 比例
const roleUserSelectComputed = computed(() => {
  //选项总数
  const ll = roleUserList.value.length
  // 勾选数
  const l = rightCheckOptionValue.value.length

  return l + '/' + ll
})

// 右侧全选
const rightCheckAll = ref(false)
// 右侧全选框中间状态
const rightIsIndeterminate = ref(false)

// 右侧全选状态变化
const rightHandleCheckAllChange = (val: CheckboxValueType) => {
  const value: string[] = roleUserList.value.map((item) => item.value)
  rightCheckOptionValue.value = val ? value : []
  rightIsIndeterminate.value = false
}

// 右侧选项框值的变化
const rightHandleCheckedChange = (value: CheckboxValueType[]) => {
  const checkedCount = value.length
  const roleUserLen = roleUserList.value.length

  rightCheckAll.value = checkedCount === roleUserLen
  rightIsIndeterminate.value = checkedCount > 0 && checkedCount < roleUserLen
}

// 防抖筛选角色用户
const throttleQueryRoleUser = throttle(() => {
  if (rightInput.value === '') {
    rightCheckOption.value = roleUserList.value
    return
  }

  rightCheckOption.value = roleUserList.value.filter((item) => {
    return item.label.includes(rightInput.value)
  })
}, 500)

watch(
  () => rightInput.value,
  () => throttleQueryRoleUser()
)

// 设置角色用户 (删除、重置、添加)
const setRoleUsers = async (type: UserDataSetTypeEnum, idList: string[]) => {
  const res = await setRoleUsersApi(props.roleInfo.id, type, idList)
  if (res.code !== 200) return openAlert.error(res.message)
  ElMessage.success(res.message)
  getRoleUsersDetail()
  queryPageUserList()

  if (type === UserDataSetTypeEnum.ADD) {
    leftCheckOptionValue.value = []
  }
  if (type === UserDataSetTypeEnum.REMOVE) {
    rightCheckOptionValue.value = []
  }
}

// 右移
const toRight = (ids: string[]) => {
  const temp: CheckBoxOptionItf[] = ids.map((item) => {
    const str = leftCheckOptionMap.value.get(item)
    rightCheckOptionMap.value.set(item, str)
    return { value: item, label: str }
  })

  roleUserList.value = [...roleUserList.value, ...temp]
  rightCheckOption.value = [...rightCheckOption.value, ...temp]
  leftCheckOptionValue.value = []
  leftCheckAll.value = false
  leftIsIndeterminate.value = false
}

// 移除
const rightRemove = (ids: string[]) => {
  const temp = roleUserList.value.filter((item) => !ids.includes(item.value))

  rightCheckOptionMap.value = new Map()

  roleUserList.value = temp.map((item) => {
    rightCheckOptionMap.value.set(item.value, item.label)
    return { value: item.value, label: item.label }
  })
  rightCheckOption.value = temp.map((item) => {
    return { value: item.value, label: item.label }
  })
  rightCheckOptionValue.value = []
  rightCheckAll.value = false
  rightIsIndeterminate.value = false
}
</script>

<style scoped lang="less">
.container {
  display: flex;
  width: 100%;
  height: 420px;

  > .center {
    width: calc(28% - 20px);
    height: 100%;
    padding: 10px;

    > .text {
      letter-spacing: 1px;
      padding-bottom: 5px;

      > .label {
        font-weight: bold;
        padding: 5px;
        color: #606266;
        font-size: 15px;
      }
    }
  }

  > .right,
  > .left {
    width: 36%;
    height: 100%;
    // overflow: auto;
    border: 1px solid #e0e2e6;
    border-radius: 4px;

    > .title {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 8px;

      > .check_label {
        display: flex;
        align-items: center;
      }
    }

    > .searchIput {
      display: flex;
      justify-content: space-between;
      padding: 8px;
    }

    > .optionBox {
      height: calc(100% - 84px);
      overflow: auto;
      display: flex;
      flex-direction: column;

      > .optionList {
        flex: 1;
        overflow: auto;
        padding-left: 15px;
      }

      > .paginationBar {
        height: 36px;
        display: flex;
        justify-content: center;
        align-items: center;
        border-top: 1px solid #e0e2e6;
        // background-color: #e0e2e6;
      }
    }
  }

  > .left {
    position: relative;

    > .btnBox {
      position: absolute;
      top: 80%;
      right: 0;
      transform: translate(100%, -50%);

      width: 100px;
      border: 1px solid #e0e2e6;
      border-radius: 0 4px 4px 0;

      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      > div {
        padding-top: 5px;
        padding-bottom: 5px;
      }
    }
  }

  > .right {
    position: relative;

    > .btnBox {
      position: absolute;
      top: 80%;
      left: 0;
      transform: translate(-100%, -50%);
      width: 100px;
      border: 1px solid #e0e2e6;
      border-radius: 4px 0 0 4px;

      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;

      > div {
        padding-top: 5px;
        padding-bottom: 5px;
      }
    }
  }
}
</style>
